﻿using UnityEngine;
using UnityEditor;
using System.Collections.Generic;

namespace CWM.Skinn
{
    public static partial class SkinnContextCommands
    {

        [CtxMenuItem("SkinnedMeshRenderer/Shapes/Extract/Single",
           "Extracts a blend-shape value at 100% as a mesh", ContextFlag.Blendshape, ContextRequirements.HasBlendshapes, 002)]
        public static void SkinnedMeshRendererShapesExtractSingle()
        {
            var contexItem = SkinnContext.GetContextItem();
            if (!contexItem) return;
            var context = contexItem.GetComponent<SkinnedMeshRenderer>();
            if (SkinnEx.IsNullOrNotInAScene(context)) { SkinnContext.Finished(); return; }
            if (!context.HasSharedMesh()) { SkinnContext.Finished(); return; }

            var sharedMesh = context.GetSharedMesh();

            var ContextShape0 = SkinnContext.ContextShape0;
            var shapeIndex = sharedMesh.GetBlendShapeIndex(ContextShape0);
            if (shapeIndex < 0) return;

            var blendShapeCount = sharedMesh.blendShapeCount;
            var weights = new float[blendShapeCount];

            for (int i = 0; i < blendShapeCount; i++)
            {
                weights[i] = context.GetBlendShapeWeight(i);
                context.SetBlendShapeWeight(i, 0f);
            }

            var renderer = context.CloneAsMeshRenderer(true) as MeshRenderer;
            renderer.SetSharedMesh(sharedMesh.Clone() as Mesh);
            renderer.name = sharedMesh.GetBlendShapeName(shapeIndex);

            context.SetBlendShapeWeight(shapeIndex, 100f);
            context.BakeBlendshapes(renderer.GetSharedMesh());
            context.SetBlendShapeWeight(shapeIndex, 0f);

            //Undo.RegisterCreatedObjectUndo(renderer.GetSharedMesh(), "Extract Single");
            Undo.RegisterCreatedObjectUndo(renderer.gameObject, "Extract Single");

            for (int i = 0; i < blendShapeCount; i++)
            {
                context.SetBlendShapeWeight(i, weights[i]);
            }

            SkinnContext.Finished();
        }

        [CtxMenuItem("SkinnedMeshRenderer/Shapes/Extract/All",
           "Extracts blend-shape value at 100% as a mesh", ContextRequirements.HasBlendshapes, 002)]
        public static void SkinnedMeshRendererShapesExtractAll()
        {

            var contexItem = SkinnContext.GetContextItem();
            if (!contexItem) return;
            var context = contexItem.GetComponent<SkinnedMeshRenderer>();
            if (SkinnEx.IsNullOrNotInAScene(context)) { SkinnContext.Finished(); return; }
            if (!context.GetSharedMesh()) { SkinnContext.Finished(); return; }

            var sharedMesh = context.GetSharedMesh();
            var blendShapeCount = sharedMesh.blendShapeCount;
            var weights = new float[blendShapeCount];

            for (int i = 0; i < blendShapeCount; i++)
            {
                weights[i] = context.GetBlendShapeWeight(i);
                context.SetBlendShapeWeight(i, 0f);
            }

            var tempMesh = sharedMesh.Clone() as Mesh;
            tempMesh.ClearBlendShapes();
            var renderers = new Renderer[blendShapeCount];
            extractGameObjectsList = new List<GameObject>();
            extractGameObjectsList.Clear();

            for (int i = 0; i < blendShapeCount; i++)
            {
                renderers[i] = context.CloneAsMeshRenderer(true) as MeshRenderer;

                renderers[i].SetSharedMesh(tempMesh.Clone() as Mesh);
                renderers[i].gameObject.name = context.GetSharedMesh().GetBlendShapeName(i);
                context.SetBlendShapeWeight(i, 100f);
                context.BakeBlendshapes(renderers[i].GetSharedMesh());
                context.SetBlendShapeWeight(i, 0f);

                extractGameObjectsList.Add(renderers[i].gameObject);

                //Undo.RegisterCreatedObjectUndo(renderers[i].GetSharedMesh(), "Extract All");
                Undo.RegisterCreatedObjectUndo(renderers[i].gameObject, "Extract All");
            }

            for (int i = 0; i < blendShapeCount; i++)
            {
                context.SetBlendShapeWeight(i, weights[i]);
            }

            SkinnEx.Release(tempMesh);

            SkinnContext.Finished();
        }

        private static List<GameObject> extractGameObjectsList = new List<GameObject>();
        public static List<GameObject> GetExtractGameObjsList()
        {
            return extractGameObjectsList;
        }

        [CtxMenuItem("SkinnedMeshRenderer/Shapes/Extract/Current Shape",
        "Extracts a blend-shape from all blend-shapes at there current value.", ContextRequirements.HasBlendshapes, 002)]
        public static void SkinnedMeshRendererShapesExtractCurrent()
        {
            var contexItem = SkinnContext.GetContextItem();
            if (!contexItem) return;
            var context = contexItem.GetComponent<SkinnedMeshRenderer>();
            if (SkinnEx.IsNullOrNotInAScene(context)) { SkinnContext.Finished(); return; }
            if (!context.HasSharedMesh()) { SkinnContext.Finished(); return; }

            var sharedMesh = context.GetSharedMesh();

            var renderer = context.CloneAsMeshRenderer(true) as MeshRenderer;
            renderer.SetSharedMesh(sharedMesh.Clone() as Mesh);

            context.BakeBlendshapes(renderer.GetSharedMesh());

            //Undo.RegisterCreatedObjectUndo(renderer.GetSharedMesh(), "Extract Single");
            Undo.RegisterCreatedObjectUndo(renderer.gameObject, "Extract Single");

            SkinnContext.Finished();
        }
    }
}